package cn.test.Async.demo;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import static cn.test.Async.AsyncCall.threadName;

/**
 * 大家注意一下，CyclicBarrier和CountDownLatch仅仅只是类似，两者还是有一定区别的。比如，一个可以理解为做加法，等到加到这个
 * 数字后一起运行；一个则是减法，减到0继续运行。一个是可以重复计数的；另一个不可以等等等等。
 * 另外，使用CyclicBarrier的时候要注意两点:
 *     第一点，初始化的时候，参数数字要设为2，因为异步调用这里是一个线程，而主线程是一个线程，两个线程都await的时候才能继续执行，
 *          这也是和CountDownLatch区别的部分。
 *     第二点，也是关于初始化参数的数值的，和这里的demo无关，在平时编程的时候，需要比较小心，如果这个数值设置得很大，
 *          比线程池中的线程数都大，那么就很容易引起死锁了。
 **/
//利用CyclicBarrier
public class Demo5 extends BaseDemo{
    private CyclicBarrier cyclicBarrier = new CyclicBarrier(2);

    @Override
    public void callback(long response) {

        System.out.println(threadName() +"得到结果");
        System.out.println(threadName() +response);
        System.out.println(threadName() +"调用结束");

        try {
            cyclicBarrier.await();//自增1，等到countDownLatch 累加到 == 2时，唤醒主线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Demo5 demo5 = new Demo5();
        demo5.call();
        try {
            demo5.cyclicBarrier.await(); //countDownLatch == 2时，唤醒
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println("主线程内容");
    }
}
